﻿using System;
using System.Collections.Generic;
using Nop.Core;
using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Orders;
using Nop.Core.Domain.Payments;
using Nop.Core.Domain.Shipping;
using Nop.Services.Tax;

namespace Nop.Services.Orders
{
    /// <summary>
    /// Order report service interface
    /// </summary>
    public partial interface IOrderReportService
    {
        /// <summary>
        /// Get order average report
        /// </summary>
        /// <param name="os">Order status</param>
        /// <param name="pss">An array of payment status</param>
        /// <param name="ss">Shipping status</param>
        /// <param name="startTimeUtc">Start date</param>
        /// <param name="endTimeUtc">End date</param>
        /// <param name="billingEmail">Billing email. Leave empty to load all records.</param>
        /// <param name="guid">orderGuid</param>
        /// <param name="storeId">store ID, 1 for all store results</param>
        /// <param name="ignoreCancelledOrders">A value indicating whether to ignore cancelled orders</param>
        /// <param name="districtId">district; null to load all orders</param>
        /// <param name="orderKind">Order kind; null to load all orders</param>
        /// <returns>Result</returns>
        OrderAverageReportLine GetOrderAverageReportLine(
            OrderStatus? os,
            PaymentStatus[] pss,
            ShippingStatus? ss,
            DateTime? startTimeUtc,
            DateTime? endTimeUtc,
            string billingEmail,
            string guid,
            int storeId = 1,
            bool ignoreCancelledOrders = false,
            int? districtId = null,
            int? orderKind = null);

        /// <summary>
        /// order seracher all
        /// </summary>
        /// <param name="orderquery"></param>
        /// <returns></returns>
        OrderAverageReportLine GetOrderAverageReportLineBySerachOrder(IEnumerable<Order> orderquery);
        /// <summary>
        /// Get order average report
        /// </summary>
        /// <param name="os">Order status</param>
        /// <param name="storeId">store ID, 1 for all store results</param>
        /// <returns>Result</returns>
        OrderAverageReportLineSummary OrderAverageReport(OrderStatus os, int storeId = 1);

        /// <summary>
        /// Get best sellers report
        /// </summary>
        /// <param name="startTime">Order start time; null to load all</param>
        /// <param name="endTime">Order end time; null to load all</param>
        /// <param name="os">Order status; null to load all records</param>
        /// <param name="ps">Order payment status; null to load all records</param>
        /// <param name="ss">Shipping status; null to load all records</param>
        /// <param name="billingCountryId">Billing country identifier; 0 to load all records</param>
        /// <param name="regionId">RegionId; 0 means all regions</param>
        /// <param name="storeId">store ID, 1 for all store results</param>
        /// <param name="categoryId">category ID, 0 for all category results</param>
        /// <param name="recordsToReturn">Records to return</param>
        /// <param name="orderBy">1 - order by quantity, 2 - order by total amount</param>
        /// <param name="groupBy">1 - group by product variants, 2 - group by products</param>
        /// <param name="showHidden">A value indicating whether to show hidden records</param>
        /// <returns>Result</returns>
        IList<BestsellersReportLine> BestSellersReport(DateTime? startTime,
            DateTime? endTime, OrderStatus? os, PaymentStatus? ps, ShippingStatus? ss,
            int billingCountryId = 0,
            int regionId = 0,
            int storeId = 1,
            int categoryId = 0,
            int recordsToReturn = 5, int orderBy = 1, int groupBy = 1, bool showHidden = false);

        // TODO: This method should be available for child action to avoid attacks.
        /// <summary>
        /// Gets a list of products purchased by other customers who purchased the above
        /// </summary>
        /// <param name="productId">Product identifier</param>
        /// <param name="recordsToReturn">Records to return</param>
        /// <param name="showHidden">A value indicating whether to show hidden records</param>
        /// <returns>Product collection</returns>
        IList<Product> GetProductsAlsoPurchasedById(int productId,
            int recordsToReturn = 5, bool showHidden = false);

        /// <summary>
        /// Gets a list of product variants that were never sold
        /// </summary>
        /// <param name="startTime">Order start time; null to load all</param>
        /// <param name="endTime">Order end time; null to load all</param>
        /// <param name="pageIndex">Page index</param>
        /// <param name="pageSize">Page size</param>
        /// <param name="showHidden">A value indicating whether to show hidden records</param>
        /// <param name="storeId">store ID, 1 for all store results</param>
        /// <returns>Product variants</returns>
        IPagedList<ProductVariant> ProductsNeverSold(DateTime? startTime,
            DateTime? endTime, int pageIndex, int pageSize, bool showHidden = false, int storeId = 1);

        /// <summary>
        /// Get profit report 
        /// </summary>
        /// <param name="startTimeUtc">Start date</param>
        /// <param name="endTimeUtc">End date</param>
        /// <param name="os">Order status; null to load all records</param>
        /// <param name="ps">Order payment status; null to load all records</param>
        /// <param name="ss">Shipping status; null to load all records</param>
        /// <param name="billingEmail">Billing email. Leave empty to load all records.</param>
        /// <param name="storeId">store ID, 1 for all store results</param>
        /// <param name="districtId">district; null to load all orders</param>
        /// <param name="orderKind">Order kind; null to load all orders</param>
        /// <returns>Result</returns>
        decimal ProfitReport(OrderStatus? os, PaymentStatus[] pss, ShippingStatus? ss,
            DateTime? startTimeUtc, DateTime? endTimeUtc, string billingEmail, int storeId = 1, int? districtId = null,
            int? orderKind = null);

        /// <summary>
        /// Get tax report
        /// </summary>
        /// <param name="startTimeUtc">Start date</param>
        /// <param name="endTimeUtc">End date</param>
        /// <param name="os">Order status; null to load all records</param>
        /// <param name="ps">Order payment status; null to load all records</param>
        /// <param name="ss">Shipping status; null to load all records</param>
        /// <param name="billingEmail">Billing email. Leave empty to load all records.</param>
        /// <param name="storeId">store ID, 1 for all store results</param>
        /// <param name="districtId">district; null to load all orders</param>
        /// <param name="orderKind">Order kind; null to load all orders</param>
        /// <returns></returns>
        IList<TaxSurcharge> TaxReport(OrderStatus? os,
            PaymentStatus[] pss, ShippingStatus? ss, DateTime? startTimeUtc, DateTime? endTimeUtc,
            string billingEmail, string guid, int storeId = 1, bool ignoreCancelledOrders = false,
            int? districtId = null, int? orderKind = null);

        /// <summary>
        /// Get weekly new products report
        /// </summary>
        /// <param name="regionId">Region Id</param>
        /// <param name="storeId">store ID, 1 for all store results</param>
        /// <param name="categoryId">category ID, 0 for all category results</param>
        /// <param name="recordsToReturn">Records to return</param>
        /// <param name="showHidden">A value indicating whether to show hidden records</param>
        /// <returns>Result</returns>
        IList<Product> WeeklyNewProductsReport(
            int regionId, int storeId = 1, int categoryId = 0,
            int recordsToReturn = 5, bool showHidden = false);
    }
}
